PHP / Ajax / Javascript Navigation menu

For this example to work you need ajax.js. Have a look at Ajax calling script to create this file.

We will need some form of data to create this menu, so in this example we will use MySQL. You may retrieve the data any way you like as long as it comes out as an associative array, so that you can loop through each menu item.

Here is the query to create your MySQL menu table.

CREATE TABLE  `examples`.`menu` (
`id` int(11) NOT NULL DEFAULT ‘0’,
`label` varchar(65) NOT NULL,
`link_url` varchar(100) NOT NULL DEFAULT ‘#’,
`parent_id` int(11) NOT NULL DEFAULT ‘0’,
`title` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

now that you have your table you will need to add some menu items. We will just focus on the following 2 fields.

  • label will be our menu item name
  • parent_id will be the parent of a menu item
  • Now enter the following the data as shown below. If the parent_id is 0 that means the menu item belongs to the main menu.

    id label parent_id
    1 Home 0
    2 Products 0
    3 News 0
    4 Contact Us 0
    5 About Us 0
    6 Product 1 2
    7 Product 2 2
    8 Sub Product 1 7
    9 Sub Product 2 7
    10 Sub Product 3 7
    11 Email 4
    12 Phone 4
    13 Product Test 10

    Before we create our index.php file, we are going to create a file to store our classes and then we will create a class to call the MySQL database. We shall call it classes.php.

    <?php

    class database {

    private $host, $user, $pass;

    public function __construct ($ihost, $iuser, $ipass) {
    $this->host = $ihost;
    $this->user = $iuser;
    $this->pass = $ipass;
    }

    public function Connect () {
    mysql_connect ($this->host, $this->user, $this->pass)
    OR die (‘There was a problem connecting to the Database.’);
    }

    public function SelectDB ($database) {
    mysql_select_db ($database)
    OR die (‘Database Not Found.’);
    }

    }
    ?>

    Now we shall create our index.php file.

    <html>
    <head>
    <link href=”normal.css” rel=”stylesheet” type=”text/css” />
    <script src=”menu.js” type=”text/javascript” language=”javascript”></script>
    <script src=”ajax.js” type=”text/javascript” language=”javascript”></script>
    </head>
    <body>
    <?php

    include ‘classes.php’;

    $conn = new database(‘localhost’,’testuser’,’testuser’);
    $conn->Connect();
    $conn->SelectDB(‘examples’);

    $query = sprintf(‘SELECT id, label, link_url, parent_id, title FROM menu WHERE parent_id=0’);
    $result=mysql_query($query) or die(mysql_error());

    $markup = ”;

    echo ‘<div>’;
    while ($info = mysql_fetch_assoc($result))  {
    echo ‘<li onmouseover=”loadAjax(\’loadmenu.php?id=’.$info[‘id’].’\’);”>’;
    echo $info[‘label’].'</li>’;
    $markup .= ‘<div id=”leftmenu”‘.$info[‘id’].'” class=”menufield” ></div>’;
    }
    echo ‘</div>’;
    echo ‘<div>’.$markup.'</div>’;

    ?>
    </body>
    </html>

    In the index.php we do the following

    1. Get the CSS and Javascript
    2. connect to the database
    3. Loop through each menu item with parent_id = 0, 0 is the main menu
    4. Create this menu in bullets in a div with a div next to it for the child menu.
    5. load the child menu when the mouse is over the parent menu item.

    Lets add in our CSS and Javascript before we add in the ajax. I called the CSS file normal.css, this menu has very simple styling so there is plenty of scope to style it to how you want to style it.

    .leftmenu {float:left; text-align: left; list-style: none;}

    .leftmenu li {padding-top: 3px; padding-bottom: 3px; margin-top: 1px;}
    .leftmenu li:hover {background: #99b; color: #009; cursor: pointer;}
    .lident {background: #eee;}

    .menufield {height: 27px;}

    And now for menu.js

    function checkParent(element, parent){
    while(element.parentNode){
    element=element.parentNode;
    if(element.id==parent){return true;}
    }
    return false;
    }

    function loadAjax (url, delay, addtime) {
    var d = new Date();
    time = d.getTime();
    var e = (url.match(/\?/gi) == “?”) ? “&” : “?”;
    setTimeout(‘loadXMLDoc(“‘+url+e+’d=’+escape(time)+'”, true);’, delay);
    }

    document.onmouseover = function (event) {
    el = (document.elementFromPoint) ? document.elementFromPoint(mouseX(event), mouseY(event)) : ”;
    menunum=new Array();

    var mdiv=document.getElementsByTagName(‘div’);
    var t;
    for (var i=0;i&ltmdiv.length;i++) {
    if (mdiv[i].id) {
    if (mdiv[i].id.substr(0,8) == ‘leftmenu’) {
    menunum.push(mdiv[i].id.substr(8));
    }
    }
    }

    for (i = 0; i <= menunum.length; i++) {
    if (document.getElementById(“leftmenu”+menunum[i])) {
    if (checkParent(el,”leftmenu”+menunum[i]) == false  && checkParent(el, “leftmenu”+menunum[i]) == false) {
    document.getElementById(“leftmenu”+menunum[i]).innerHTML = ”;
    }
    }
    }
    }

    function mouseX(evt) {
    evt = (evt) ? evt : ((event) ? event : null);
    if (evt.pageX) return evt.pageX;
    if (evt.clientX)
    return evt.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
    else return null;
    }

    function mouseY(evt) {
    evt = (evt) ? evt : ((event) ? event : null);
    if (evt.pageY) return evt.pageY;
    else if (evt.clientY)
    return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
    else return null;
    }

    function createDiv (id, html, width, height, left, top, bcolor, disableback) {

    var newdiv = document.createElement(‘div’);
    newdiv.setAttribute(‘id’, id);

    if (width) {newdiv.style.width = 300;}
    if (height) {newdiv.style.height = 300;}
    if (bcolor) {newdiv.style.background = bcolor;}

    if ((left || top) || (left && top)) {
    if (left) {newdiv.style.left = left;}
    if (top) {newdiv.style.top = top;}
    }

    if (html) {newdiv.innerHTML = html;} else {newdiv.innerHTML = ”    “;}

    document.body.appendChild(newdiv);
    }

    function removeDiv(div){
    if (document.getElementById(div)) {
    document.getElementById(div).parentNode.removeChild(document.getElementById(div));
    }
    }

    I created a function loadAjax, which calls the ajax file but it adds a unique date parameter at the end to make the call unique.
    when document.onmousemove fires, it does the following

    1. Checks to see what element the mouse is over with elementFromPoint (This does not work in Netscape)
    2. Goes through each div element looking for the elements that start with ‘leftmenu’, and then gets the id associated with that menu.
    3. Loops through the array of menus and then clears the contents of the HTML.

    For a more detailed explanation for the rest of the functions look at the following

    now finally for our ajax file, loadmenu.php

    <?php

    include ‘classes.php’;

    $conn = new database(‘localhost’,’testuser’,’testuser’);
    $conn->Connect();
    $conn->SelectDB(‘examples’);

    $id = $_GET[‘id’];

    $query = sprintf(‘SELECT id, label, link_url, parent_id, title FROM menu WHERE parent_id=”%s”‘, mysql_escape_string($id));
    $result = mysql_query($query) or die(mysql_error());

    $markup = ”;
    if (mysql_num_rows($result) > 0) {
    $markup2 = “”;
    $markup .= “<div class=’leftmenu’>”;
    while ($info = mysql_fetch_assoc($result)) {
    $markup .= “<li class=’lident’ onmouseover=’loadAjax(\\\”loadmenu.php?id=$info[id]\\\”);’>”;
    $markup .= “$info[label]</li>”;
    $markup2 .= “<div id=’leftmenu$info[id]’ class=’menufield’></div>”;
    }
    $markup .= “</div>”;
    $markup .= “<div class=’leftmenu’>$markup2</div>”;
    }

    header(“Content-Type: text/xml”);

    echo <<<EOT
    <actions>
    <action>
    <method>script</method>
    <![CDATA[document.getElementById(“leftmenu$id”).innerHTML = “$markup”;]]></code>
    </action>
    </actions>
    EOT;

    ?>

    You will notice it is more or less a duplicate of the index.php because all you doing is loading the menu with a different parent_id and changing the styling so that it floats left, next to the parent menu.

    And that is it, you can now add your own data and change the styling to meet your needs.

    Have a look at my site http://www.techfind.co.uk to download this example.

    function checkParent(element, parent){
    while(element.parentNode){
    element=element.parentNode;
    if(element.id==parent){return true;}
    }
    return false;
    }function loadAjax (url, delay, addtime) {
    var d = new Date();
    time = d.getTime();
    var e = (url.match(/\?/gi) == “?”) ? “&” : “?”;
    setTimeout(‘loadXMLDoc(“‘+url+e+’d=’+escape(time)+'”, true);’, delay);
    }document.onmouseover = function (event) {
    el = (document.elementFromPoint) ? document.elementFromPoint(mouseX(event), mouseY(event)) : ”;
    menunum=new Array();//    if (id == ‘all’) {
    var mdiv=document.getElementsByTagName(‘div’);
    var t;
    for (var i=0;i
    if (mdiv[i].id) {
    if (mdiv[i].id.substr(0,8) == ‘leftmenu’) {
    menunum.push(mdiv[i].id.substr(8));
    }
    }
    }
    //    } else {
    //        menunum.push(id.substr(8));
    //    }for (i = 0; i <= menunum.length; i++) {
    if (document.getElementById(“leftmenu”+menunum[i])) {
    if (checkParent(el,”leftmenu”+menunum[i]) == false  && checkParent(el, “leftmenu”+menunum[i]) == false) {
    document.getElementById(“leftmenu”+menunum[i]).innerHTML = ”;
    }
    }
    }
    }

    function mouseX(evt) {
    evt = (evt) ? evt : ((event) ? event : null);
    if (evt.pageX) return evt.pageX;
    if (evt.clientX)
    return evt.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
    else return null;
    }

    function mouseY(evt) {
    evt = (evt) ? evt : ((event) ? event : null);
    if (evt.pageY) return evt.pageY;
    else if (evt.clientY)
    return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
    else return null;
    }

    function createDiv (id, html, width, height, left, top, bcolor, disableback) {

    var newdiv = document.createElement(‘div’);
    newdiv.setAttribute(‘id’, id);

    if (width) {newdiv.style.width = 300;}
    if (height) {newdiv.style.height = 300;}
    if (bcolor) {newdiv.style.background = bcolor;}

    if ((left || top) || (left && top)) {
    if (left) {newdiv.style.left = left;}
    if (top) {newdiv.style.top = top;}
    }

    if (html) {newdiv.innerHTML = html;} else {newdiv.innerHTML = ”    “;}

    document.body.appendChild(newdiv);
    }

    function removeDiv(div){
    if (document.getElementById(div)) {
    document.getElementById(div).parentNode.removeChild(document.getElementById(div));
    }
    }


    About this entry